package javalight.network.ro.server;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import org.xsocket.connection.INonBlockingConnection;

/**
 * 数据缓冲器
 * 缓冲接收到的数据，并包装成一个Request
 * @author Ruby
 *
 */
public class DataStore implements Runnable{

	public static final int MAX_LENGTH = 1024*1024*2;//2M
	public int bufferSize = 1024*10;

	ByteBuffer bb;
	int expectLength = 0;
	int currentLength = 0;
	Throwable exception;
	
	List<IMessageHandler> handlers = new ArrayList<IMessageHandler>();
	
	public DataStore()
	{
		bb = ByteBuffer.allocate(bufferSize);
	}
	
	INonBlockingConnection connection;
	public DataStore(INonBlockingConnection connection, int bufferSize)
	{
		this.connection = connection;
		this.bufferSize = bufferSize;
		bb = ByteBuffer.allocate(bufferSize);
	}
	
	@Override
	public void run() {
		int len;
		try {
			len = connection.read(bb);
			bb.flip();
			if(currentLength==0)
			{
				expectLength = (int) bb.getLong();
				if(expectLength > MAX_LENGTH)
				{
					exception = new DataException("message head is not well formatted.");
					return;
				}
				if(len == expectLength)
				{
					for(IMessageHandler item : handlers)
						item.onMessage(connection, new String(bb.array(), (8+2), len-(8+2)));
					resetBuffer();
				}
				else if(len<expectLength)
				{
					currentLength += len;
				}
				else if(len>expectLength)
				{
					for(IMessageHandler item : handlers)
						item.onMessage(connection, new String(bb.array(), (8+2), expectLength-(8+2)));
					currentLength = (len-expectLength);
					ByteBuffer bb2 = ByteBuffer.allocate(bufferSize);
					bb2.put(bb.array(), expectLength, currentLength);
					bb = bb2;
				}
			}
			else
			{
				currentLength += len;
				
			}
			//System.out.println(new String(bb.array(), bb.position(), len));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void addMessageHandler(IMessageHandler handler)
	{
		handlers.add(handler);
	}
	
	private void resetBuffer()
	{
		bb.clear();
		expectLength = 0;
		currentLength = 0;
		exception = null;
	}

}
